docs: def _make_image_to_vec_tito(feature_name, tmp_dir=None, checkpoint=None):
    """Creates a tensor-in-tensor-out function that produces embeddings from image bytes.
  
    Image to embedding is implemented with Tensorflow's inception v3 model and a pretrained
    checkpoint. It returns 1x2048 'PreLogits' embeddings for each image.
  
    Args:
      feature_name: The name of the feature. Used only to identify the image tensors so
        we can get gradients for probe in image prediction explaining.
      tmp_dir: a local directory that is used for downloading the checkpoint. If
        non, a temp folder will be made and deleted.
      checkpoint: the inception v3 checkpoint gs or local path. If None, default checkpoint
        is used.
  
    Returns: a tensor-in-tensor-out function that takes image string tensor and returns embeddings.
    """
  
    def _image_to_vec(image_str_tensor):
  
      def _decode_and_resize(image_tensor):
        """Decodes jpeg string, resizes it and returns a uint8 tensor."""
  
        # These constants are set by Inception v3's expectations.
        height = 299
        width = 299
        channels = 3
  
        image_tensor = tf.where(tf.equal(image_tensor, ''), IMAGE_DEFAULT_STRING, image_tensor)
  
        # Fork by whether image_tensor value is a file path, or a base64 encoded string.
        slash_positions = tf.equal(tf.string_split([image_tensor], delimiter="").values, '/')
        is_file_path = tf.cast(tf.count_nonzero(slash_positions), tf.bool)
  
        # The following two functions are required for tf.cond. Note that we can not replace them
        # with lambda. According to TF docs, if using inline lambda, both branches of condition
        # will be executed. The workaround is to use a function call.
        def _read_file():
          return tf.read_file(image_tensor)
  
        def _decode_base64():
          return tf.decode_base64(image_tensor)
  
        image = tf.cond(is_file_path, lambda: _read_file(), lambda: _decode_base64())
        image = tf.image.decode_jpeg(image, channels=channels)
        image = tf.expand_dims(image, 0)
        image = tf.image.resize_bilinear(image, [height, width], align_corners=False)
        image = tf.squeeze(image, squeeze_dims=[0])
        image = tf.cast(image, dtype=tf.uint8)
        return image
  
      # The CloudML Prediction API always "feeds" the Tensorflow graph with
      # dynamic batch sizes e.g. (?,).  decode_jpeg only processes scalar
      # strings because it cannot guarantee a batch of images would have
      # the same output size.  We use tf.map_fn to give decode_jpeg a scalar
      # string from dynamic batches.
      image = tf.map_fn(_decode_and_resize, image_str_tensor, back_prop=False, dtype=tf.uint8)
      image = tf.image.convert_image_dtype(image, dtype=tf.float32)
      # "gradients_[feature_name]" will be used for computing integrated gradients.
      image = tf.identity(image, name='gradients_' + feature_name)
      image = tf.subtract(image, 0.5)
      inception_input = tf.multiply(image, 2.0)
  
      # Build Inception layers, which expect a tensor of type float from [-1, 1)
      # and shape [batch_size, height, width, channels].
      with tf.contrib.slim.arg_scope(inception_v3_arg_scope()):
        _, end_points = inception_v3(inception_input, is_training=False)
  
      embeddings = end_points['PreLogits']
      inception_embeddings = tf.squeeze(embeddings, [1, 2], name='SpatialSqueeze')
      return inception_embeddings
  
    def _tito_from_checkpoint(tito_in, checkpoint, exclude):
      """ Create an all-constants tito function from an original tito function.
  
      Given a tensor-in-tensor-out function which contains variables and a checkpoint path,
      create a new tensor-in-tensor-out function which includes only constants, and can be
      used in tft.map.
      """
  
      def _tito_out(tensor_in):
        checkpoint_dir = tmp_dir
        if tmp_dir is None:
          checkpoint_dir = tempfile.mkdtemp()
  
        g = tf.Graph()
        with g.as_default():
          si = tf.placeholder(dtype=tensor_in.dtype, shape=tensor_in.shape, name=tensor_in.op.name)
          so = tito_in(si)
          all_vars = tf.contrib.slim.get_variables_to_restore(exclude=exclude)
          saver = tf.train.Saver(all_vars)
          # Downloading the checkpoint from GCS to local speeds up saver.restore() a lot.
          checkpoint_tmp = os.path.join(checkpoint_dir, 'checkpoint')
          with file_io.FileIO(checkpoint, 'r') as f_in, file_io.FileIO(checkpoint_tmp, 'w') as f_out:
            f_out.write(f_in.read())
          with tf.Session() as sess:
            saver.restore(sess, checkpoint_tmp)
            output_graph_def = tf.graph_util.convert_variables_to_constants(sess,
                                                                            g.as_graph_def(),
                                                                            [so.op.name])
          file_io.delete_file(checkpoint_tmp)
          if tmp_dir is None:
            shutil.rmtree(checkpoint_dir)
  
        tensors_out = tf.import_graph_def(output_graph_def,
                                          input_map={si.name: tensor_in},
                                          return_elements=[so.name])
        return tensors_out[0]
  
      return _tito_out
  
    if not checkpoint:
      checkpoint = INCEPTION_V3_CHECKPOINT
    return _tito_from_checkpoint(_image_to_vec, checkpoint, INCEPTION_EXCLUDED_VARIABLES)