class_docstr: Keras model doesn't support variable scope reuse.
  This is a wrapper around keras model to mimic reuse.
docstr: Args:
      input_tensors ([tf.Tensor])
  Returns:
      output tensors of this tower, evaluated with the input tensors.
docstr_tok: ["Args",":","input_tensors","(","[","tf.Tensor","]",")","Returns",":","output","tensors","of","this","tower",",","evaluated","with","the","input","tensors","."]
code: def __call__(self, *input_tensors):
      """
      Args:
          input_tensors ([tf.Tensor])
      Returns:
          output tensors of this tower, evaluated with the input tensors.
      """
      reuse = tf.get_variable_scope().reuse
  
      old_trainable_names = {x.name for x in tf.trainable_variables()}
      trainable_backup = backup_collection(
          [tf.GraphKeys.TRAINABLE_VARIABLES]
      )
      update_ops_backup = backup_collection([tf.GraphKeys.UPDATE_OPS])
  
      def post_process_model(model):
          added_trainable_names = {
              x.name for x in tf.trainable_variables()
          }
          restore_collection(trainable_backup)
  
          for v in model.weights:
              # In Keras, the collection is not respected and could contain non-trainable vars.
              # We put M.weights into the collection instead.
              if (
                  v.name not in old_trainable_names
                  and v.name in added_trainable_names
              ):
                  tf.add_to_collection(
                      tf.GraphKeys.TRAINABLE_VARIABLES, v
                  )
          new_trainable_names = {
              x.name for x in tf.trainable_variables()
          }
  
          for n in added_trainable_names:
              if n not in new_trainable_names:
                  logger.warn(
                      "Keras created trainable variable '{}' which is actually not trainable. "
                      "This was automatically corrected.".format(n)
                  )
  
          # Keras models might not use this collection at all (in some versions).
          # This is a BC-breaking change of tf.keras: https://github.com/tensorflow/tensorflow/issues/19643
          restore_collection(update_ops_backup)
          for op in model.updates:
              tf.add_to_collection(tf.GraphKeys.UPDATE_OPS, op)
  
      if self.cached_model is None:
          assert not reuse
  
          # starting from some versions, tf.keras starts to prepend name scope to variable names ..
          @contextmanager
          def clear_tower0_name_scope():
              ns = tf.get_default_graph().get_name_scope()
              if ns == "tower0":
                  with tf.name_scope("/"):
                      yield
              else:
                  yield
  
          with clear_tower0_name_scope():
              model = self.cached_model = self.get_model(*input_tensors)
              assert isinstance(
                  model, keras.Model
              ), "Your get_model function should return a `tf.keras.Model`!"
          outputs = model.outputs
      elif reuse:
          # use the cached Keras model to mimic reuse
          # NOTE: ctx.is_training won't be useful inside model,
          # because inference will always use the cached Keras model
          model = self.cached_model
          outputs = model.call(*input_tensors)
      else:
          # create new Keras model if not reuse
          model = self.get_model(*input_tensors)
          outputs = model.outputs
  
      post_process_model(model)
  
      if isinstance(outputs, list) and len(outputs) == 1:
          return outputs[0]
      return outputs
  
imports: from contextlib import contextmanager
  import six
  import tensorflow
  from tensorflow import keras
  from ..callbacks import Callback, CallbackToHook, InferenceRunner, InferenceRunnerBase, ScalarStats
  from ..models.regularize import regularize_cost_from_collection
  from ..tfutils.collection import backup_collection, restore_collection
  from ..tfutils.common import get_op_tensor_name
  from ..tfutils.scope_utils import cached_name_scope
  from ..tfutils.summary import add_moving_summary
  from ..tfutils.tower import get_current_tower_context
  from ..train import SimpleTrainer, SyncMultiGPUTrainerParameterServer, Trainer
  from ..train.interface import apply_default_prefetch
  from ..train.trainers import DistributedTrainerBase
  from ..utils import logger
  from ..utils.gpu import get_nr_gpu
label_desc: Use image node_id 2 for calling the KerasModelCaller obj's underlying member method code with example usage: obj.__call__() and returns: outputs, outputs