input: Write a function that decodes LibSVM input to tensors using TensorFlow. The function, named `decode_libsvm`, should accept the following arguments: `input` (a `Tensor` of type `string`), `num_features` (an `int` that is `>= 1`), `dtype` (an optional `tf.DType` from: `tf.float32, tf.float64, tf.int32, tf.int64`. Defaults to `tf.float32`), `label_dtype` (an optional `tf.DType` from: `tf.float32, tf.float64, tf.int32, tf.int64`. Defaults to `tf.int64`), and `name` (a name for the operation, optional). The function should return a tuple of `Tensor` objects `(label, feature_indices, feature_values, feature_shape)`, where `label` is a `Tensor` of type `label_dtype`, `feature_indices` is a `Tensor` of type `int64`, `feature_values` is a `Tensor` of type `dtype`, and `feature_shape` is a `Tensor` of type `int64`.
  
  
  assert decode_libsvm("0 1:1 2:2", 3) == (0, [1, 2], [1, 2], [3])
  assert decode_libsvm("1 1:1", 2) == (1, [1], [1], [2])
  assert decode_libsvm("", 4) == (None, [], [], [4])
  
output: def decode_libsvm(input, num_features, dtype=tf.float32, label_dtype=tf.int64, name=None):
      def parse_libsvm(line):
          tokens = tf.strings.split([line], ' ')
          label = tf.strings.to_number(tokens[0], out_type=label_dtype) if tokens[0] else None
          indices = []
          values = []
          for token in tokens[1:]:
              if token:
                  idx, val = tf.strings.split([token], ':')
                  indices.append(tf.strings.to_number(idx, out_type=tf.int64))
                  values.append(tf.strings.to_number(val, out_type=dtype))
          return label, indices, values, [num_features]
  
      label, indices, values, shape = tf.map_fn(parse_libsvm, input, dtype=(label_dtype, tf.int64, dtype, tf.int64), infer_shape=False)
      return label, tf.stack(indices), tf.stack(values), tf.constant(shape, dtype=tf.int64)