keras/src/backend/tensorflow/trainer.py/TensorFlowTrainer/_symbolic_build
class TensorFlowTrainer:    def _symbolic_build(self, iterator=None, data_batch=None):
        if self._distribute_strategy is None:
            # When no distribution strategy is set, defer building
            # to when the train/test/predict function gets traced.
            # This maximizes backwards compatibility.
            return

        # Unlike jax/torch iterator, tf iterator returns an iterator instead
        # of data batch in `iterator.enumerate_epoch()`.
        if iterator is not None:
            for _, it in iterator.enumerate_epoch():
                maybe_distributed_data_batch = next(it)
                has_distributed_values = tree.map_structure(
                    lambda x: isinstance(x, tf.distribute.DistributedValues),
                    maybe_distributed_data_batch,
                )
                if all(tree.flatten(has_distributed_values)):
                    data_batch = self.distribute_strategy.reduce(
                        "MEAN",
                        maybe_distributed_data_batch,
                        axis=None,
                    )
                else:
                    data_batch = maybe_distributed_data_batch
                break
        super()._symbolic_build(data_batch=data_batch)