docstr: Run `func` on all GPUs (towers) and return the results.
  
  Args:
      towers (list[int]): a list of GPU id.
      func: a lambda to be called inside each tower
      devices: a list of devices to be used. By default will use '/gpu:{tower}'
      use_vs (list[bool]): list of use_vs to passed to TowerContext
  
  Returns:
      List of outputs of ``func``, evaluated on each tower.
docstr_tok: ["Run","`","func","`","on","all","GPUs","(","towers",")","and","return","the","results",".","Args",":","towers","(","list","[","int","]",")",":","a","list","of","GPU","id",".","func",":","a","lambda","to","be","called","inside","each","tower","devices",":","a","list","of","devices","to","be","used",".","By","default","will","use","'\/gpu",":","{","tower","}","'","use_vs","(","list","[","bool","]",")",":","list","of","use_vs","to","passed","to","TowerContext","Returns",":","List","of","outputs","of","``","func","``",",","evaluated","on","each","tower","."]
code: def call_for_each_tower(towers, func, devices=None, use_vs=None):
      """
      Run `func` on all GPUs (towers) and return the results.
  
      Args:
          towers (list[int]): a list of GPU id.
          func: a lambda to be called inside each tower
          devices: a list of devices to be used. By default will use '/gpu:{tower}'
          use_vs (list[bool]): list of use_vs to passed to TowerContext
  
      Returns:
          List of outputs of ``func``, evaluated on each tower.
      """
  
      ret = []
      if devices is not None:
          assert len(devices) == len(towers)
      if use_vs is not None:
          assert len(use_vs) == len(towers)
  
      tower_names = [
          "tower{}".format(idx) for idx in range(len(towers))
      ]
  
      for idx, t in enumerate(towers):
          device = (
              devices[idx]
              if devices is not None
              else "/gpu:{}".format(t)
          )
          usevs = use_vs[idx] if use_vs is not None else False
          reuse = not usevs and idx > 0
          with tfv1.device(device), _maybe_reuse_vs(
              reuse
          ), TrainTowerContext(
              tower_names[idx],
              vs_name=tower_names[idx] if usevs else "",
              index=idx,
              total=len(towers),
          ):
              if (
                  len(str(device)) < 10
              ):  # a device function doesn't have good string description
                  logger.info(
                      "Building graph for training tower {} on device {} ...".format(
                          idx, device
                      )
                  )
              else:
                  logger.info(
                      "Building graph for training tower {} ...".format(
                          idx
                      )
                  )
  
              # When use_vs is True, use LOCAL_VARIABLES,
              # so these duplicated variables won't be saved by default.
              with override_to_local_variable(enable=usevs):
                  ret.append(func())
      return ret
  
imports: import copy
  import pprint
  import re
  from abc import ABCMeta, abstractmethod
  from contextlib import contextmanager
  import six
  import tensorflow
  from ..compat import tfv1
  from ..tfutils.common import get_tf_version_tuple
  from ..tfutils.gradproc import ScaleGradient
  from ..tfutils.tower import TrainTowerContext
  from ..utils import logger
  from ..utils.develop import HIDE_DOC
  from .utils import GradientPacker, LeastLoadedDeviceSetter, aggregate_grads_colocate, allreduce_grads_naive, allreduce_grads, allreduce_grads_hierarchical, merge_grad_list, override_to_local_variable, split_grad_list
label_desc: Use image node_id 3 for calling the DataParallelBuilder obj's underlying member method code with example usage: obj.call_for_each_tower(towers, func, devices, use_vs) and returns: ret