code: func FinishPop(ctx context.Context, ops ...*PopOp) (tombs Garbage, err error) {
  	txn := datastore.CurrentTransaction(ctx)
  
  	entities := []*tombstonesEntity{}
  	tombsCount := 0
  	for _, op := range ops {
  		if op.finished {
  			panic("the operation has already been finished")
  		}
  		if op.txn != txn {
  			panic("wrong transaction")
  		}
  		if op.dirty {
  			entities = append(entities, op.makeTombstonesEntity())
  			tombsCount += len(op.popped)
  		}
  	}
  
  	if err := datastore.Put(ctx, entities); err != nil {
  		return nil, transient.Tag.Apply(err)
  	}
  
  	if tombsCount != 0 {
  		tombs = make(Garbage, 0, tombsCount)
  	}
  	for _, op := range ops {
  		tombs = append(tombs, op.popped...)
  		op.finished = true
  	}
  
  	return tombs, nil
  }
docs: ////////////////////////////////////////////////////////////////////////////////
  // FinishPop completes one or more pop operations (for different sets) by
  // submitting changes to datastore.
  //
  // Must be called within the same transaction that called BeginPop.
  //
  // It returns a list of tombstones for popped items. The storage used by the
  // items can be reclaimed right away by calling 'CleanupGarbage'. It is fine
  // not to do so, 'List' will eventually return all tombstones that need cleaning
  // anyway. Calling 'CleanupGarbage' as best effort is still beneficial though,
  // since it will reduce the amount of garbage in the set.
  //
  // Returns only transient errors.