input: Write a function to decode LibSVM input to tensors using TensorFlow. 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 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(["1 1:1 2:2", "2 3:3 4:4"], 4, dtype=tf.float32, label_dtype=tf.int32) == (label_tensor, feature_indices_tensor, feature_values_tensor, feature_shape_tensor)
  assert decode_libsvm([], 4, dtype=tf.float64, label_dtype=tf.int64) == (empty_label_tensor, empty_feature_indices_tensor, empty_feature_values_tensor, empty_feature_shape_tensor)
  assert decode_libsvm(["1 1:1 2:2", "2 3:3 4:4"], 2, dtype=tf.int32, label_dtype=tf.int32) == (label_tensor_2, feature_indices_tensor_2, feature_values_tensor_2, feature_shape_tensor_2)
output: def decode_libsvm(input, num_features, dtype=tf.float32, label_dtype=tf.int64, name=None):
      with tf.name_scope(name, "decode_libsvm", [input, num_features, dtype, label_dtype]):
          def parse_line(line):
              parts = tf.strings.split([line], ' ')
              label = tf.strings.to_number(parts[0], out_type=label_dtype)
              features = parts[1:]
              indices = tf.strings.to_number(tf.strings.split(features, ':')[0::2], out_type=tf.int64)
              values = tf.strings.to_number(tf.strings.split(features, ':')[1::2], out_type=dtype)
              return label, indices, values
          
          labels, indices, values = tf.map_fn(
              parse_line,
              input,
              dtype=(label_dtype, tf.int64, dtype),
              name="map_parse_line"
          )
          
          feature_indices = tf.reshape(indices, [-1])
          feature_values = tf.reshape(values, [-1])
          feature_shape = tf.stack([tf.shape(input)[0], num_features])
          
          return labels, feature_indices, feature_values, feature_shape