input: Write a function to decode LibSVM input to tensors using TensorFlow. The function should take a `Tensor` of type `string` named `input`, an integer `num_features` that is `>= 1`, an optional `dtype` of type `tf.DType` (defaulting to `tf.float32`), an optional `label_dtype` of type `tf.DType` (defaulting to `tf.int64`), and an optional name for the operation. The function should return a tuple of `Tensor` objects `(label, feature_indices, feature_values, feature_shape)`, where `label` is of type `label_dtype`, `feature_indices` is of type `int64`, `feature_values` is of type `dtype`, and `feature_shape` is of type `int64`.
  assert decode_libsvm(["1 1:1 3:1", "2 2:1 3:1"], 4, tf.float32, tf.int64) == (tf.Tensor([1, 2]), tf.Tensor([[0, 1], [0, 3], [1, 2], [1, 3]]), tf.Tensor([1., 1., 1., 1.]), tf.Tensor([2, 4]))
  assert decode_libsvm(["1 1:1", "2 2:1"], 3, tf.float64, tf.float32) == (tf.Tensor([1., 2.]), tf.Tensor([[0, 1], [1, 2]]), tf.Tensor([1., 1.]), tf.Tensor([2, 3]))
  assert decode_libsvm([], 5) == (tf.Tensor([]), tf.Tensor([]), tf.Tensor([]), tf.Tensor([]))
output: def decode_libsvm(input, num_features, dtype=tf.float32, label_dtype=tf.int64, name=None):
      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.strings.to_number(idx, out_type=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=name
      )
  
      labels = tf.stack(labels)
      indices = tf.ragged.stack(indices_list).flat_values
      values = tf.ragged.stack(values_list).flat_values
      shape = tf.stack([tf.shape(input, out_type=tf.int64)[0], tf.constant(num_features, dtype=tf.int64)])
  
      return labels, indices, values, shape