docs: def build_tfexample_transfored_training_input_fn(schema,
                                                   features,
                                                   analysis_output_dir,
                                                   raw_data_file_pattern,
                                                   training_batch_size,
                                                   num_epochs=None,
                                                   randomize_input=False,
                                                   min_after_dequeue=1,
                                                   reader_num_threads=1,
                                                   allow_smaller_final_batch=True):
    """Creates training input_fn that reads transformed tf.example files.
  
    Args:
      schema: schema list
      features: features dict
      analysis_output_dir: output folder from analysis
      raw_data_file_pattern: file path, or list of files
      training_batch_size: An int specifying the batch size to use.
      num_epochs: numer of epochs to read from the files. Use None to read forever.
      randomize_input: If true, the input rows are read out of order. This
          randomness is limited by the min_after_dequeue value.
      min_after_dequeue: Minimum number elements in the reading queue after a
          dequeue, used to ensure a level of mixing of elements. Only used if
          randomize_input is True.
      reader_num_threads: The number of threads enqueuing data.
      allow_smaller_final_batch: If false, fractional batches at the end of
          training or evaluation are not used.
  
    Returns:
      An input_fn suitable for training that reads transformed data in tf record
        files of tf.example.
    """
  
    def transformed_training_input_fn():
      """Training input function that reads transformed data."""
  
      if isinstance(raw_data_file_pattern, six.string_types):
        filepath_list = [raw_data_file_pattern]
      else:
        filepath_list = raw_data_file_pattern
  
      files = []
      for path in filepath_list:
        files.extend(file_io.get_matching_files(path))
  
      filename_queue = tf.train.string_input_producer(
          files, num_epochs=num_epochs, shuffle=randomize_input)
  
      options = tf.python_io.TFRecordOptions(
          compression_type=tf.python_io.TFRecordCompressionType.GZIP)
      ex_id, ex_str = tf.TFRecordReader(options=options).read_up_to(
          filename_queue, training_batch_size)
  
      queue_capacity = (reader_num_threads + 3) * training_batch_size + min_after_dequeue
      if randomize_input:
        _, batch_ex_str = tf.train.shuffle_batch(
            tensors=[ex_id, ex_str],
            batch_size=training_batch_size,
            capacity=queue_capacity,
            min_after_dequeue=min_after_dequeue,
            enqueue_many=True,
            num_threads=reader_num_threads,
            allow_smaller_final_batch=allow_smaller_final_batch)
  
      else:
        _, batch_ex_str = tf.train.batch(
            tensors=[ex_id, ex_str],
            batch_size=training_batch_size,
            capacity=queue_capacity,
            enqueue_many=True,
            num_threads=reader_num_threads,
            allow_smaller_final_batch=allow_smaller_final_batch)
  
      feature_spec = {}
      feature_info = get_transformed_feature_info(features, schema)
      for name, info in six.iteritems(feature_info):
        if info['size'] is None:
          feature_spec[name] = tf.VarLenFeature(dtype=info['dtype'])
        else:
          feature_spec[name] = tf.FixedLenFeature(shape=[info['size']], dtype=info['dtype'])
  
      parsed_tensors = tf.parse_example(batch_ex_str, feature_spec)
  
      # Expand the dims of non-sparse tensors. This is needed by tf.learn.
      transformed_features = {}
      for k, v in six.iteritems(parsed_tensors):
        if isinstance(v, tf.Tensor) and v.get_shape().ndims == 1:
          transformed_features[k] = tf.expand_dims(v, -1)
        else:
          # Sparse tensor
          transformed_features[k] = v
  
      transformed_features = image_feature_engineering(
          features=features,
          feature_tensors_dict=transformed_features)
  
      # Remove the target tensor, and return it directly
      target_name = get_target_name(features)
      if not target_name or target_name not in transformed_features:
        raise ValueError('Cannot find target transform in features')
  
      transformed_target = transformed_features.pop(target_name)
  
      return transformed_features, transformed_target
  
    return transformed_training_input_fn