class_docstr: A tower function (see
  `tutorial on tower function
  <http://tensorpack.readthedocs.io/tutorial/extend/trainer.html#tower-trainer>`_)
  It keeps track of the name scope, variable scope and input/output tensors
  each time the function is called.
  
  :class:`TowerTrainer` needs this so that it knows how to build a predictor.
  
  Conceptually, this class is roughly equivalent to `tf.function` with input signature, introduced in TF 2.0.
class_docstr_tok: ["A","tower","function","(","see","`","tutorial","on","tower","function","<","http",":","\/\/tensorpack.readthedocs.io\/tutorial\/extend\/trainer.html","#","tower-trainer",">","`","_",")","It","keeps","track","of","the","name","scope",",","variable","scope","and","input\/output","tensors","each","time","the","function","is","called",".",":","class",":","`","TowerTrainer","`","needs","this","so","that","it","knows","how","to","build","a","predictor",".","Conceptually",",","this","class","is","roughly","equivalent","to","`","tf.function","`","with","input","signature",",","introduced","in","TF","2.0","."]
docstr: Args:
      tower_func: a function which builds one tower in the graph.
          It takes several input tensors and could return anything.
      input_signature ([TensorSpec]): list of :class:`tf.TensorSpec`.
          They are used to figure out the names for the input tensors.
docstr_tok: ["Args",":","tower_func",":","a","function","which","builds","one","tower","in","the","graph",".","It","takes","several","input","tensors","and","could","return","anything",".","input_signature","(","[","TensorSpec","]",")",":","list","of",":","class",":","`","tf.TensorSpec","`",".","They","are","used","to","figure","out","the","names","for","the","input","tensors","."]
code: def __init__(self, tower_fn, input_signature):
      """
      Args:
          tower_func: a function which builds one tower in the graph.
              It takes several input tensors and could return anything.
          input_signature ([TensorSpec]): list of :class:`tf.TensorSpec`.
              They are used to figure out the names for the input tensors.
      """
      assert callable(tower_fn), tower_fn
      self._inputs_names = [k.name for k in input_signature]
      assert len(set(self._inputs_names)) == len(
          self._inputs_names
      ), "Duplicated names in input_signature! " + str(
          self._inputs_names
      )
      if any(x is None for x in self._inputs_names):
          raise ValueError(
              "Input signature cannot have empty names! Got "
              + str(self._inputs_names)
          )
      for name in self._inputs_names:
          if any(k in name for k in [":", "/", " "]):
              raise ValueError("Invalid input name: '{}'".format(name))
      self._tower_fn = tower_fn
      self._input_signature = input_signature
  
      self._handles = []
  
imports: from abc import ABCMeta, abstractmethod, abstractproperty
  import six
  from ..compat import tfv1
  from ..utils import logger
  from ..utils.argtools import call_only_once
  from ..utils.develop import HIDE_DOC
  from ..utils.naming import MOVING_SUMMARY_OPS_KEY
  from .collection import CollectionGuard
  from .common import get_op_or_tensor_by_name, get_op_tensor_name
label_desc: Use image node_id 1 to create a new TowerFunc object from inherited base classes: object with example: obj = TowerFunc(tower_fn, input_signature)