def write_summaries(self, tagged_data, experiment_name, run_name):
    """Transactionally writes the given tagged summary data to the DB.

    Args:
      tagged_data: map from tag to TagData instances.
      experiment_name: name of experiment.
      run_name: name of run.
    """
    logger.debug('Writing summaries for %s tags', len(tagged_data))
    # Connection used as context manager for auto commit/rollback on exit.
    # We still need an explicit BEGIN, because it doesn't do one on enter,
    # it waits until the first DML command - which is totally broken.
    # See: https://stackoverflow.com/a/44448465/1179226
    with self._db:
      self._db.execute('BEGIN TRANSACTION')
      run_id = self._maybe_init_run(experiment_name, run_name)
      tag_to_metadata = {
          tag: tagdata.metadata for tag, tagdata in six.iteritems(tagged_data)
      }
      tag_to_id = self._maybe_init_tags(run_id, tag_to_metadata)
      tensor_values = []
      for tag, tagdata in six.iteritems(tagged_data):
        tag_id = tag_to_id[tag]
        for step, wall_time, tensor_proto in tagdata.values:
          dtype = tensor_proto.dtype
          shape = ','.join(str(d.size) for d in tensor_proto.tensor_shape.dim)
          # Use tensor_proto.tensor_content if it's set, to skip relatively
          # expensive extraction into intermediate ndarray.
          data = self._make_blob(
              tensor_proto.tensor_content or
              tensor_util.make_ndarray(tensor_proto).tobytes())
          tensor_values.append((tag_id, step, wall_time, dtype, shape, data))
      self._db.executemany(
          """
          INSERT OR REPLACE INTO Tensors (
            series, step, computed_time, dtype, shape, data
          ) VALUES (?, ?, ?, ?, ?, ?)
          """,
          tensor_values)