input: Write a function to decode LibSVM input to tensors using TensorFlow operations. The function 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 returns 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(["1 1:1 3:1", "2 1:2 2:2"], 3, tf.float32, tf.int32, "decode_libsvm")==(array([1, 2], dtype=int32), array([[0, 1], [0, 3], [1, 1], [1, 2]]), array([1., 1., 2., 2.], dtype=float32), array([2, 3]))
  assert decode_libsvm(["1 1:1", "2 1:2"], 2, tf.float64, tf.int64)==(array([1, 2], dtype=int64), array([[0, 1], [1, 1]]), array([1., 2.], dtype=float64), array([2, 2]))
  assert decode_libsvm(["1 1:1"], 1)==(array([1], dtype=int64), array([[0, 1]]), array([1.], dtype=float32), array([1, 1]))
  assert decode_libsvm([], 1)==(array([], dtype=int64), array([]), array([], dtype=float32), array([0, 1]))
output: def decode_libsvm(input, num_features, dtype=tf.float32, label_dtype=tf.int64, name=None):
      with tf.name_scope(name or "decode_libsvm"):
          def parse_line(line):
              parts = tf.strings.split(line, ' ')
              label = tf.strings.to_number(parts[0], out_type=label_dtype)
              indices = []
              values = []
              for part in parts[1:]:
                  idx, val = tf.strings.split(part, ':')
                  indices.append([tf.cast(tf.strings.to_number(idx, out_type=tf.int64), tf.int64)])
                  values.append(tf.strings.to_number(val, out_type=dtype))
              return label, indices, values
  
          labels, indices_list, values_list = tf.map_fn(
              parse_line, input, dtype=(label_dtype, tf.int64, dtype),
              infer_shape=False, name="map_parse_line"
          )
  
          labels = tf.stack(labels)
          indices = tf.reshape(tf.concat(indices_list, axis=0), [-1, 1])
          values = tf.concat(values_list, axis=0)
          feature_shape = tf.stack([tf.shape(input)[0], num_features])
  
          return labels, indices, values, feature_shape