def batched_placeholders_from_specs(specs):
  """Returns placeholders for the given tf.TypeSpecs or feature specs.

  Args:
    specs: a Dict[Text, Union[tf.TypeSpec, FeatureSpec]]. Note that the values
      in this dict must be of the same type. Mixing is not allowed.

  Returns:
    A dictionary from strings to `Tensor`, `SparseTensor`s, or `RaggedTensor`s.

  Raises:
    ValueError: when the TypeSpec or feature spec has an unsupported dtype.
  """
  if not (all([_is_feature_spec(s) for s in specs.values()]) or
          all([isinstance(s, tf.TypeSpec) for s in specs.values()])):
    raise TypeError('Specs must be all tf.TypeSpecs or feature specs. '
                    'Mixing is not allowed. Got: {}'.format(specs))

  result = {}
  for name, spec in specs.items():
    if isinstance(spec, tf.RaggedTensorSpec):
      # TODO(b/159717195): clean up protected-access
      spec_dtype = spec._dtype  # pylint: disable=protected-access
    else:
      spec_dtype = spec.dtype
    if spec_dtype not in (tf.int64, tf.float32, tf.string):
      raise ValueError('Feature {} ({}, {}) had invalid dtype'.format(
          name, spec, type(spec)))
    if isinstance(spec, tf.TypeSpec):
      result[name] = _batched_placeholder_from_typespec(name, spec)
    else:
      result[name] = _batched_placeholder_from_feature_spec(name, spec)

  return result
Returns placeholders for the given tf.TypeSpecs or feature specs.

  Args:
    specs: a Dict[Text, Union[tf.TypeSpec, FeatureSpec]]. Note that the values
      in this dict must be of the same type. Mixing is not allowed.

  Returns:
    A dictionary from strings to `Tensor`, `SparseTensor`s, or `RaggedTensor`s.

  Raises:
    ValueError: when the TypeSpec or feature spec has an unsupported dtype.
  
tensorflow_transform/impl_helper.py