Sorry to be hammering this point, but I was mid-post when Shixiong Zhu posted. As both Shu and Samuel mentioned, zip definitely seems to be the correct operator for combining two observables in matched pairs.
e.g.
Observable.zip(imageObservable, metaDataObservable, new Func2<Image, Metadata, TupleOrSomething>() {
@Override
public TupleOrSomething call(Image img, Metadata meta) {
return new TupleOrSomething(img, meta);
}
}).subscribe(new Subscriber<TupleOrSomething>() {...});