This is because the functions you're passing to then all close over the variable i, not the value that variable has when you create the functions. So later, when the functions are called, they all see the value of i as it is then, after the loop is complete (100).
If you want to capture the value of i as it is when you create the function, you can use ES5's Function#bind:
for ( i = 0; i < 100; i++) {
browser.manage().logs().get('browser').then(function(index, browserLog) {
console.log(index);
}.bind(null, i));
}
bind returns a new function that, when called, will call the original function with a given this value (in this case I'm using null) and any arguments you follow that with, followed by arguments given to the function bind returned.
Another approach is a builder function:
for ( i = 0; i < 100; i++) {
browser.manage().logs().get('browser').then(buildHandler(i));
}
function buildHandler(index) {
return function(browserLog) {
console.log(index);
};
}
That has the advantage of allowing the caller to control this.