def METHOD_NAME(self, bottleneck, labels, scope="head"):
    """Appends the train signature of the model to the current graph.
    Bottleneck and labels tensors are connected as inputs.
    All model variables are converted to placeholders and returned
    in a list.
    Args:
      bottleneck: tensor containing input bottlenecks.
      labels: tensor containing one-hot ground truth labels.
      scope: name of the scope to load the model into.
    Returns:
      (loss tensor, list of variable gradients, list of variable placeholders)
    """
    logits, [ws, bs], flat_bottleneck = self._logits(bottleneck, scope)
    with tf.name_scope(scope + "/loss"):
        predictions = tf.nn.softmax(logits)
        cross_entropy = -tf.reduce_sum(labels * tf.math.log(predictions), 1)
        loss = tf.reduce_mean(cross_entropy)
        if self._l2_reg is not None:
            loss += self._l2_reg * tf.reduce_sum(ws**2)
    with tf.name_scope(scope + "/backprop"):
        # d_bs is also equal to combined sigmoid and cross-entropy gradient.
        d_bs = predictions - labels
        flat_bottleneck_t = tf.transpose(flat_bottleneck)
        d_ws = tf.matmul(flat_bottleneck_t, d_bs) / self._train_batch_size
        d_bs = tf.reduce_mean(d_bs, 0)
        if self._l2_reg is not None:
            d_ws += 2 * self._l2_reg * ws
    return loss, [d_ws, d_bs], [ws, bs]