def _build_graph(self):
        self.data_manager = DataManager(datasets=self.env.datasets)
        self.data_manager.build_graph()

        data = self.data_manager.iterator.get_next()
        self.inp = data["image"]
        network_outputs = self.network(data, self.data_manager.is_training)

        network_tensors = network_outputs["tensors"]
        network_recorded_tensors = network_outputs["recorded_tensors"]
        network_losses = network_outputs["losses"]

        self.tensors = network_tensors

        self.recorded_tensors = recorded_tensors = dict(global_step=tf.train.get_or_create_global_step())

        # --- loss ---

        self.loss = tf.constant(0., tf.float32)
        for name, tensor in network_losses.items():
            self.loss += tensor
            recorded_tensors['loss_' + name] = tensor
        recorded_tensors['loss'] = self.loss

        # --- train op ---

        if cfg.do_train and not cfg.get('no_gradient', False):
            tvars = self.trainable_variables(for_opt=True)

            self.train_op, self.train_records = build_gradient_train_op(
                self.loss, tvars, self.optimizer_spec, self.lr_schedule,
                self.max_grad_norm, self.noise_schedule, grad_n_record_groups=self.grad_n_record_groups)

        sess = tf.get_default_session()
        for k, v in getattr(sess, 'scheduled_values', None).items():
            if k in recorded_tensors:
                recorded_tensors['scheduled_' + k] = v
            else:
                recorded_tensors[k] = v

        # --- recorded values ---

        intersection = recorded_tensors.keys() & network_recorded_tensors.keys()
        assert not intersection, "Key sets have non-zero intersection: {}".format(intersection)
        recorded_tensors.update(network_recorded_tensors)

        intersection = recorded_tensors.keys() & self.network.eval_funcs.keys()
        assert not intersection, "Key sets have non-zero intersection: {}".format(intersection)

        if self.network.eval_funcs:
            eval_funcs = self.network.eval_funcs
        else:
            eval_funcs = {}

        # For running functions, during evaluation, that are not implemented in tensorflow
        self.evaluator = Evaluator(eval_funcs, network_tensors, self)