How to tell when dom-repeat is done stamping elements

To access a dynamically created node in Polymer 1.x (like template repeat) use:

this.$$('#id')

For Polymer 2.x use:

this.shadowRoot.getElementById('id');

instead of this.$.id

for example if the template id is template you should use

this.$$('#template')
example
ready: function(){
    this.$$('#template').addEventListener("dom-change", function(event){
        console.log(event);
    });
},

Maybe this simple example can help explain the behaviour and extend on the comments.

<dom-module id="change-tester">
    <template>
    <h1>Change Tester</h1>
        <ul>
        <template id="template" is="dom-repeat" items="{{content}}">
            <li>{{item}}</li>
        </template>
        </ul>
        <button on-click="more">Add more</button>
    </template>
</dom-module>
<script>
    Polymer({

        is: 'change-tester',
        properties: {
            content: {
                type: Array,
                value: function(){ return ["one", "two", "three"]}
            }
        },
        ready: function(){
            this.$.template.addEventListener("dom-change", function(event){
               console.log(event);
            });
        },

        more: function(){
            this.push("content", "four");
            this.push("content", "five");
        }
    });
</script>

Whenever dom-change is fired, I log the event to the console, so open the dev tools and have a look. Initially, the dom-repeat has three iterations and will populate the dom with three elements. Note that only one event will fire, namely when all three elements have been added. If you click the button, two more items are added to the content in the repeat. As the dom-repeat updates asynchronously, these two items are again handled in one go and will only trigger one event.

So the dom-change event is actually that final event you are looking for. It will only fire again, if you manipulate the items that are bound to it.